package com.eleaf.adbb.core;

import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;

import com.eleaf.adbb.exception.ResourcesException;
import com.eleaf.adbb.model.LayoutType;
import com.eleaf.adbb.model.NameGenerater;
import com.eleaf.adbb.template.ClassTemplate;
import com.eleaf.adbb.template.android.CodeTemplate;
import com.eleaf.adbb.template.android.PropertyTemplate;
import com.eleaf.adbb.util.BaseUtil;

/**
 * 布局文件解析，并构建对应配置对象
 * 
 * @author Eleaf
 * 
 */
public class LayoutReader {

	private List<File> layoutFiles;

	private static final String ID_HEAD = "@+id/";
	private static final String ATTRIBUTR_NAME_ID = "id";
	private static final String ATTRIBUTR_NAME_CLASS = "class";
	private static final String ACTIVITY = "activity";
	private static final String FRAGMENT = "fragment";

	/**
	 * 读取布局文件并构建对应的配置对象
	 * 
	 * @param path
	 * @param activityTemplate activity模版
	 * @param fragmentTemplate fragment模版
	 * @return 模版列表
	 * @throws ResourcesException
	 */
	public List<CodeTemplate> read( String path, ClassTemplate activityTemplate, ClassTemplate fragmentTemplate ) throws ResourcesException {
		File f = new File ( path );
		layoutFiles = new ArrayList<File> ();
		loadLayoutFiles ( f, activityTemplate.getNameGenerater () );
		if ( layoutFiles.size () == 0 ) {
			throw new ResourcesException ( "\"", path, "\" does not found layout file" );
		}
		List<CodeTemplate> cfgs = new ArrayList<CodeTemplate> ();
		for ( File xmlFile : layoutFiles ) {
			String layoutName = xmlFile.getName ().trim ();
			layoutName = layoutName.substring ( 0, layoutName.lastIndexOf ( "." ) );
			LayoutType layouType = getLayouType ( layoutName );
			if ( layouType == LayoutType.ACTIVITY ) {
				cfgs.add ( buildConfig ( xmlFile, layoutName, activityTemplate ) );
			} else {
				cfgs.add ( buildConfig ( xmlFile, layoutName, fragmentTemplate ) );
			}
		}
		return cfgs;
	}

	/**
	 * 构建生成布局代码的模版
	 * 
	 * @param f 布局文件
	 * @param layoutName 布局文件名称
	 * @param classTemplate 模版
	 * @return 用于生成布局代码的模版
	 * @throws ResourcesException
	 */
	private CodeTemplate buildConfig( File f, String layoutName, ClassTemplate classTemplate ) throws ResourcesException {
		NameGenerater ng = classTemplate.getNameGenerater ();
		CodeTemplate template = new CodeTemplate ( classTemplate.getLayoutType (), layoutName, ng.generateHostPackage (), classTemplate.isUseRoboGuice () );

		template.addImport ( classTemplate.getImports () );
		template.addMethod ( classTemplate.getMethods () );
		template.addVariable ( classTemplate.getVariables () );

		template.setSuperClassName ( classTemplate.getSuperClassName () );
		template.setSuperInterfaceNames ( classTemplate.getSuperInterfaceNames () );
		template.setLayoutType ( classTemplate.getLayoutType () );
		// template.setHostPackage(ng.generateHostPackage());
		template.setLastPackage ( ng.generateLastPackage ( classTemplate.getLayoutType () ) );
		template.setLayoutName ( layoutName );
		template.setUseRoboGuice ( classTemplate.isUseRoboGuice () );
		template.setClassName ( ng.generateClassName ( layoutName, classTemplate.getLayoutType () ) );
		template.addProperty ( parsePropertys ( f, ng ) );
		return template;
	}

	/**
	 * 解析布局文件属性
	 * 
	 * @param layoutFile 布局文件
	 * @param ng 命名规则生成器
	 * @return 布局文件定义了"id"属性的标签
	 */
	public List<PropertyTemplate> parsePropertys( File layoutFile, NameGenerater ng ) {
		List<PropertyTemplate> vts = new ArrayList<PropertyTemplate> ();
		try {
			XMLInputFactory inputFactory = XMLInputFactory.newInstance ();
			XMLStreamReader reader = inputFactory.createXMLStreamReader ( new FileReader ( layoutFile ) );
			while (reader.hasNext ()) {
				switch (reader.getEventType ()) {
					case XMLStreamReader.START_ELEMENT:
						String type = reader.getLocalName ();
						String attributeValue = reader.getAttributeValue ( "http://schemas.android.com/apk/res/android", ATTRIBUTR_NAME_ID );
						if ( attributeValue != null && attributeValue.indexOf ( ID_HEAD ) == 0 ) {
							String propertyId = attributeValue.substring ( ID_HEAD.length (), attributeValue.length () );
							String variableName = ng.generateVariableName ( propertyId );
							PropertyTemplate vpcfg;
							if ( type.equals ( "fragment" ) ) {
								String fragmentClass = reader.getAttributeValue ( null, ATTRIBUTR_NAME_CLASS );
								vpcfg = new PropertyTemplate ( variableName, fragmentClass, fragmentClass.substring ( fragmentClass.lastIndexOf ( "." ) + 1 ) );
								vpcfg.setFragment ( true );
							} else if ( type.indexOf ( "." ) >= 0 ) {
								vpcfg = new PropertyTemplate ( variableName, type, type.substring ( type.lastIndexOf ( "." ) + 1 ) );
								vpcfg.setFragment ( false );
							} else {
								// TODO View package
								vpcfg = new PropertyTemplate ( variableName, BaseUtil.appendString ( "android.widget.", type ), type );
								vpcfg.setFragment ( false );
							}
							vpcfg.setPropertyId ( propertyId );
							vts.add ( vpcfg );
						}
						break;
				}
				reader.next ();
			}
		} catch ( Exception e ) {
			e.printStackTrace ();
		}
		return vts;
	}

	/**
	 * 读取布局文件
	 * 
	 * @param f 布局文件
	 * @param ng 命名规则生成器
	 * @throws ResourcesException
	 */
	private void loadLayoutFiles( File f, NameGenerater ng ) throws ResourcesException {
		if ( f.isDirectory () ) {
			File[] t = f.listFiles ();
			for ( int i = 0; i < t.length; i++ ) {
				if ( t[i].isDirectory () ) {
					loadLayoutFiles ( t[i], ng );
				} else {
					if ( ng.layoutFileFilte ( t[i] ) ) {
						layoutFiles.add ( t[i] );
					}
				}
			}
		}else{
			if ( ng.layoutFileFilte (f ) ) {
				layoutFiles.add ( f);
			}
		}
	}

	/**
	 * 获取布局文件的类型（Activity、Fragment）
	 * 
	 * @param fileName 布局文件名称，不包含拓展名与路径
	 * @return
	 * @throws ResourcesException
	 */
	private LayoutType getLayouType( String fileName ) throws ResourcesException {
		if ( fileName == null || fileName.trim ().isEmpty () )
			throw new ResourcesException ( "is not found \'", fileName, "\'" );
		String[] split = fileName.split ( "_" );
		if ( split.length < 2 )
			throw new ResourcesException ( "\'", fileName, "\' is unexpected's fileName" );
		String type = split[split.length - 1].toLowerCase ();
		if ( type.equals ( FRAGMENT ) )
			return LayoutType.FRAGMENT;
		if ( type.equals ( ACTIVITY ) )
			return LayoutType.ACTIVITY;
		else
			throw new ResourcesException ( "\'", fileName, "\' is unexpected's type" );
	}

}
